/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version.  The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* OpenSceneGraph Public License for more details.
*/

#ifndef DB_FILEUTILS
#define DB_FILEUTILS 1

//#include <osgDB/Registry>

#include "kernel/dll_cfg.h"
#include "kernel/string_def.h"
#include "kernel/string_def.h"

#include <vector>
#include <deque>
#include <string>
#include <stdio.h>

namespace FD
{
	namespace Kernel
	{
		enum CaseSensitivity
		{
			CASE_SENSITIVE,
			CASE_INSENSITIVE
		};
		class Options;

		typedef std::deque<String> FilePathList;

		/** Overload of the standard fopen function. If _USE_UTF8_FILENAME is defined,
		* filename will be expanded from UTF8 to UTF16 and _wfopen will be called. */
		//extern FD_Kernel_Export FILE* fopen(const char* filename, const char* mode);

		/** Make a new directory.  Returns true if directory exists or was created. */
		//extern FD_Kernel_Export bool makeDirectory( const String &directoryPath );

		/** Make a new directory for a given file. */
		//extern FD_Kernel_Export bool makeDirectoryForFile( const String &filePath );

		/** Get current working directory. */
		//extern FD_Kernel_Export String getCurrentWorkingDirectory( void );

		/** Set current working directory. */
		//extern FD_Kernel_Export bool setCurrentWorkingDirectory( const String &newCurrentWorkingDirectory );


		/** return true if a file exists. */
		//extern FD_Kernel_Export bool fileExists(const String& filename);

		enum FileType
		{
			FILE_NOT_FOUND,
			REGULAR_FILE,
			DIRECTORY
		};

		/** return type of file. */
		extern FD_Kernel_Export FileType fileType(const String& filename);

		/** find specified file in specified file path.*/
		extern FD_Kernel_Export String findFileInPath(const String& filename, const FilePathList& filePath,CaseSensitivity caseSensitivity=CASE_SENSITIVE);

		/** return the directory/filename of a file if its is contained within specified directory.
		* return "" if directory does not contain file.  If caseInsensitive is set to true then
		* a case insensitive comparison is used to compare fileName to directory contents.
		* This is useful when unix programs attempt read case insensitive windows filenames.
		*/
		extern FD_Kernel_Export String findFileInDirectory(const String& fileName,const String& dirName,CaseSensitivity caseSensitivity=CASE_SENSITIVE);

		/** simple list of names to represent a directory's contents. */
		typedef std::vector<String> DirectoryContents;

		/** Return the contents of a directory.
		* Return value will contain filenames only, not absolute paths.
		* Returns an empty array on any error.*/
		extern FD_Kernel_Export DirectoryContents getDirectoryContents(const String& dirName);

		/** Return the contents of a directory, sorting the names into alphabetic and numberical order.
		* Return value will contain filenames only, not absolute paths.
		* Returns an empty array on any error.*/
		extern FD_Kernel_Export DirectoryContents getSortedDirectoryContents(const String& dirName);

		/** Return the list of filenames that match the given filename with wildcards.
		* Will only expand '*', and will not expand wildcards in directory, only in
		* filename part of the given filename.
		* Return value will contain path+filename so that if ever the above
		* limitation (expanding wildcards in directory) is fixed, client code will
		* still work unchanged. */
		extern FD_Kernel_Export DirectoryContents expandWildcardsInFilename(const String& filename);

		namespace FileOpResult
		{
			enum Value
			{
				OK,                          /**< Operation done. */
				SOURCE_EQUALS_DESTINATION,   /**< Operation is useless (source == destination). */
				BAD_ARGUMENT,
				SOURCE_MISSING,              /**< Source file doesn't exist. */
				SOURCE_NOT_OPENED,           /**< Error opening source file. */
				DESTINATION_NOT_OPENED,      /**< Error opening destination file. */
				READ_ERROR,
				WRITE_ERROR
			};
		}

		/** Copy a file to another location, overwriting if necessary.
		* You must provide full path for both source and destination.
		* \return true on success, or if source and destination are the same.
		* \todo Replace the implementation with filesystem functions from TR2 when available.
		*/
		//extern FD_Kernel_Export FileOpResult::Value copyFile(const String & source, const String & destination);



		//inline void setDataFilePathList(const FilePathList& filepath) { FD::Kernel::Registry::instance()->setDataFilePathList(filepath); }

		//inline void setDataFilePathList(const String& paths) { FD::Kernel::Registry::instance()->setDataFilePathList(paths); }

		//inline FilePathList& getDataFilePathList() { return FD::Kernel::Registry::instance()->getDataFilePathList(); }

		/** Search for specified file in file system, checking the DataFilePathList for possible paths,
		* returning the full path of the first valid file found, return an empty string if no string is found.
		*/
		//extern FD_Kernel_Export String findDataFile(const String& filename,CaseSensitivity caseSensitivity=CASE_SENSITIVE);

		/** Search for specified file in file system, checking first the database path set in the Options structure, then the DataFilePathList for possible paths,
		* returning the full path of the first valid file found, return an empty string if no string is found.
		*/
		//extern FD_Kernel_Export String findDataFile(const String& filename,const Options* options, CaseSensitivity caseSensitivity=CASE_SENSITIVE);

		//inline void setLibraryFilePathList(const FilePathList& filepaths) { FD::Kernel::Registry::instance()->setLibraryFilePathList(filepaths); }

		//inline void setLibraryFilePathList(const String& paths) { FD::Kernel::Registry::instance()->setLibraryFilePathList(paths); }

		//inline FilePathList& getLibraryFilePathList() { return FD::Kernel::Registry::instance()->getLibraryFilePathList(); }

		//extern FD_Kernel_Export String findLibraryFile(const String& filename,CaseSensitivity caseSensitivity=CASE_SENSITIVE);

		/** convert a string containing a list of paths delimited either with ';' (Windows) or ':' (All other platforms) into FilePath representation.*/
		extern FD_Kernel_Export void convertStringPathIntoFilePathList(const String& paths,FilePathList& filepath);

		/** Return true if FilePathList contains a filepath that is significies checking of the current working directory.*/
		extern FD_Kernel_Export bool containsCurrentWorkingDirectoryReference(const FilePathList& paths);

		extern FD_Kernel_Export void appendPlatformSpecificLibraryFilePaths(FilePathList& filepath);
		extern FD_Kernel_Export void appendPlatformSpecificResourceFilePaths(FilePathList& filepath);

		extern FD_Kernel_Export bool isRelativePath(const String& fileName);
		extern FD_Kernel_Export String getFullPath(const String& relativeTo, const String& relativePath);
	}        // namespace osgDB
}
#endif
